package prestar.dominio.entidades;

import prestar.dominio.Plazo;
import prestar.dominio.Tasa;
import java.text.DecimalFormat;
import java.text.Format;
import java.util.*;

public class Financiamiento 
{
    private int codigo;
    
    private Date fecha;
    
    private String tipo;

    private double capital;

    private String frecCuotas;

    private Tasa tasa = new Tasa();

    private Plazo plazo = new Plazo();

    private Cliente cliente;

    private Garante garante;

    private Cobrador cobrador;

    private List<Cuota> cuotas = new ArrayList<Cuota>();

    public Financiamiento() {
        this.fecha = new Date();
    }
    
    public boolean isNew()
    {
        return this.codigo < 1;
    }

    public Financiamiento(String tipo, double capital, String frecCuotas, double cantTasa, 
            String frecTasa, int cantPlazo, String frecPlazo, Cliente cliente, 
            Garante garante, Cobrador cobrador) 
    {
        this.codigo = 0;
        this.fecha = new Date();
        this.tipo = tipo;
        this.capital = capital;
        this.frecCuotas = frecCuotas;
        this.tasa = new Tasa(cantTasa, frecTasa);
        this.plazo = new Plazo(cantPlazo, frecPlazo);
        this.cliente = cliente;
        this.garante = garante;
        this.cobrador = cobrador;
        this.cuotas = new ArrayList<Cuota>();
        this.generarAmortizacion();
    }

    public int getCodigo() {
        return codigo;
    }

    public void setCodigo(int codigo) {
        this.codigo = codigo;
    }

    public Date getFecha() {
        return fecha;
    }

    public void setFecha(Date fecha) {
        this.fecha = fecha;
    }
    
    

    public double getCapital() {
        return capital;
    }

    public void setCapital(double capital) {
        this.capital = capital;
    }

    public Cliente getCliente() {
        return cliente;
    }

    public void setCliente(Cliente cliente) {
        this.cliente = cliente;
    }

    public Cobrador getCobrador() {
        return cobrador;
    }

    public void setCobrador(Cobrador cobrador) {
        this.cobrador = cobrador;
    }

    public List<Cuota> getCuotas() {
        return cuotas;
    }
    public Cuota getCuota(int codigo)
    {
        Cuota cuota = null;
        for (Cuota c : this.cuotas)
            if (c.getCodigo() == codigo)
            {
                cuota = c;
                break;
            }
        return cuota;
    }
    public String[][] getCuotasAsArray() {
        String[][] arrayCuotas = new String[this.cuotas.size()][];
        for (Cuota c : this.cuotas){
            if (c.getBalance() > 0)
            arrayCuotas[this.cuotas.indexOf(c)] = new String[]{String.valueOf(c.getCodigo()), 
                util.Fechas.stringValue(c.getFecha()), String.valueOf(c.getInteres()), String.valueOf(c.getMonto()),
                String.valueOf(c.getMora()), String.valueOf(c.getInteres() + c.getMonto()), String.valueOf(c.getFinanciamiento().getCodigo())};
        }
        return arrayCuotas;
    }
    
    public String[][] getAmortizacion() {
        double cuotas = 0;
        String[][] arrayCuotas = new String[this.cuotas.size()][];
        for (Cuota c : this.cuotas)
        {
            cuotas += c.getMonto();
            arrayCuotas[this.cuotas.indexOf(c)] = new String[]{
                util.Fechas.stringValue(c.getFecha()), String.valueOf(c.getInteres()), String.valueOf(c.getMonto()),
                String.valueOf(c.getInteres() + c.getMonto()), String.valueOf(this.getCapital() - cuotas)};
        }
        return arrayCuotas;
    }

    public void setCuotas(List<Cuota> cuotas) {
        this.cuotas = cuotas;
    }

    public String getFrecCuotas() {
        return frecCuotas;
    }

    public void setFrecCuotas(String frecCuotas) {
        this.frecCuotas = frecCuotas;
    }

    public Garante getGarante() {
        return garante;
    }

    public void setGarante(Garante garante) {
        this.garante = garante;
    }

    public Plazo getPlazo() {
        return plazo;
    }

    public void setPlazo(Plazo plazo) {
        this.plazo = plazo;
    }

    public Tasa getTasa() {
        return tasa;
    }

    public void setTasa(Tasa tasa) {
        this.tasa = tasa;
    }

    public String getTipo() {
        return tipo;
    }

    public void setTipo(String tipo) {
        this.tipo = tipo;
    }
    private int calcularPeriodos()
    {
        int periodos = 0;
        
        if(this.plazo.getUnidad().equals("Años") && this.frecCuotas.equals("Anuales"))
            periodos = this.plazo.getCantidad();
        
        else if(this.plazo.getUnidad().equals("Años") && this.frecCuotas.equals("Mensuales"))
            periodos = this.plazo.getCantidad() * 12;
        
        else if(this.plazo.getUnidad().equals("Años") && this.frecCuotas.equals("Semanales"))
            periodos = this.plazo.getCantidad() * 52;
        
        else if(this.plazo.getUnidad().equals("Años") && this.frecCuotas.equals("Diarias"))
            periodos = this.plazo.getCantidad() * 365;
        
        else if(this.plazo.getUnidad().equals("Meses") && this.frecCuotas.equals("Mensuales"))
            periodos = this.plazo.getCantidad();
        
        else if(this.plazo.getUnidad().equals("Meses") && this.frecCuotas.equals("Semanales"))
            periodos = this.plazo.getCantidad() * 4;
        
        else if(this.plazo.getUnidad().equals("Meses") && this.frecCuotas.equals("Diarias"))
            periodos = this.plazo.getCantidad() * 30;
        
        else if(this.plazo.getUnidad().equals("Semanas") && this.frecCuotas.equals("Semanales"))
            periodos = this.plazo.getCantidad();
        
        else if(this.plazo.getUnidad().equals("Semanas") && this.frecCuotas.equals("Diarias"))
            periodos = this.plazo.getCantidad() * 7;
        
        else if(this.plazo.getUnidad().equals("Dias"))
            periodos = this.plazo.getCantidad();
        return periodos;
    }
    private double calcularInteres()
    {
        double interes = 0;
        
        if(this.tasa.getPeriodo().equals("Anual") && this.frecCuotas.equals("Anuales"))
            interes = this.tasa.getCantidad();
        
        else if(this.tasa.getPeriodo().equals("Anual")  && this.frecCuotas.equals("Mensuales"))
            interes = this.tasa.getCantidad() / 12;
        
        else if(this.tasa.getPeriodo().equals("Anual") && this.frecCuotas.equals("Semanales"))
            interes = this.tasa.getCantidad() / 52;
        
        else if(this.tasa.getPeriodo().equals("Anual") && this.frecCuotas.equals("Diarias"))
            interes = this.tasa.getCantidad() / 365;
        
        else if(this.tasa.getPeriodo().equals("Mensual") && this.frecCuotas.equals("Mensuales"))
            interes = this.tasa.getCantidad();
        
        else if(this.tasa.getPeriodo().equals("Mensual") && this.frecCuotas.equals("Semanales"))
            interes = this.tasa.getCantidad() / 4;
        
        else if(this.tasa.getPeriodo().equals("Mensual") && this.frecCuotas.equals("Diarias"))
            interes = this.tasa.getCantidad() / 30;
        
        else if(this.tasa.getPeriodo().equals("Semanal") && this.frecCuotas.equals("Semanales"))
            interes = this.tasa.getCantidad();
        
        else if(this.tasa.getPeriodo().equals("Semanal") && this.frecCuotas.equals("Diarias"))
            interes = this.tasa.getCantidad() / 7;
        
        else if(this.tasa.getPeriodo().equals("Mensual")  && this.frecCuotas.equals("Anuales"))
            interes = this.tasa.getCantidad() * 12;
        
        else if(this.tasa.getPeriodo().equals("Semanal") && this.frecCuotas.equals("Anuales"))
            interes = this.tasa.getCantidad() * 52;
        
        else if(this.tasa.getPeriodo().equals("Diario") && this.frecCuotas.equals("Anuales"))
            interes = this.tasa.getCantidad() * 365;
        
        else if(this.tasa.getPeriodo().equals("Semanal") && this.frecCuotas.equals("Mensuales"))
            interes = this.tasa.getCantidad() * 4;
        
        else if(this.tasa.getPeriodo().equals("Diario") && this.frecCuotas.equals("Mensuales"))
            interes = this.tasa.getCantidad() * 30;
        
        else if(this.tasa.getPeriodo().equals("Diario") && this.frecCuotas.equals("Semanales"))
            interes = this.tasa.getCantidad() * 7;
        
        else if(this.tasa.getPeriodo().equals("Diario"))
            interes = this.tasa.getCantidad();
        return interes / 100;
    }
    private boolean completo()
    {
        boolean ok = true;
        if (this.getCapital() == 0)
            ok = false;
        else if (this.getTasa().getCantidad() == 0)
            ok = false;
        else if (this.getTasa().getPeriodo() == null)
            ok = false;
        else if (this.getPlazo().getCantidad() == 0)
            ok = false;
        else if (this.getPlazo().getUnidad() == null)
            ok = false;
        else if (this.getFrecCuotas() == null)
            ok = false;
        return ok;
    }
    public void generarAmortizacion() 
    {
        this.cuotas = new ArrayList<Cuota>();
        if (!this.completo())
            return;
        int periodos = this.calcularPeriodos();
        double interes = this.calcularInteres();
        double cinteres = 0;
        double cuota = util.Numeros.redondear(this.capital / periodos, 2);
        double ax = 0;
        double cuotas = 0;
        Cuota c = new Cuota();
        Calendar fecha = Calendar.getInstance();
        fecha.setTime(this.getFecha());
        for (int i = 0; i <= periodos; i++)
        {
            c = this.cuotas.size() > 0 ? this.cuotas.get(this.cuotas.size() - 1) : null;
            if (c != null) 
            {
                cuotas += c.getMonto();
                fecha.setTime(c.getFecha());
                if (this.frecCuotas.equals("Anuales"))
                    fecha.add(Calendar.YEAR, 1);
                else if (this.frecCuotas.equals("Mensuales"))
                    fecha.add(Calendar.MONTH, 1);
                else if (this.frecCuotas.equals("Semanales"))
                    fecha.add(Calendar.WEEK_OF_YEAR, 1);
                else
                    fecha.add(Calendar.DAY_OF_YEAR, 1);
            }
            double capitalVivo = util.Numeros.redondear(this.getCapital() - cuotas, 2);
            if(this.getTipo().equals("Método lineal"))
            {
                cinteres = c == null ? 0 : util.Numeros.redondear(capitalVivo * interes, 2);
            }
            else if(this.getTipo().equals("Capital + interés"))
            {
                cinteres = c == null ? 0 : util.Numeros.redondear(this.getCapital() * interes, 2);
            }
            else if(this.getTipo().equals("Solo interés"))
            {
                cinteres = c == null ? 0 : util.Numeros.redondear(this.getCapital() * interes, 2);
                cuota = 0;
                if (i == periodos)
                    cuota = this.getCapital();
            }
            else if (this.getTipo().equals("Método francés"))
            {
                ax = this.getCapital() * interes / (1 - Math.pow((1 + interes), periodos * -1));
                cinteres = c == null ? 0 : util.Numeros.redondear(capitalVivo * interes, 2);
                cuota = util.Numeros.redondear(ax - cinteres, 2);
            }
            
            this.cuotas.add(new Cuota(fecha.getTime(), cinteres,
                    c == null ? 0 : cuota));
        }
    }
    public String[][] getAmortizacionToArray() throws Exception
    {
        double totalCuotas = 0;
        String[][] amortizacion = new String[this.cuotas.size()][];
        if (this.cuotas.size() < 1)
            return amortizacion;
        for (Cuota c : this.cuotas)
        {
            totalCuotas += c.getMonto();
            amortizacion[this.cuotas.indexOf(c)] = new String[]{util.Fechas.stringValue(c.getFecha()), String.valueOf(c.getInteres()), 
                String.valueOf(c.getMonto()), String.valueOf(util.Numeros.redondear(c.getMonto() + c.getInteres(), 2)), String.valueOf(util.Numeros.redondear(this.getCapital() - totalCuotas, 2))};
        }
        
        return amortizacion;
    }
    public double totalCobrado()
    {
        double total = 0;
        for (Cuota c : this.getCuotas())
        {
            total += c.cobrado();
        }
        return total;
    }
    
    public double valorDelPrestamo()
    {
        double valor = 0;
        for (Cuota c : this.getCuotas())
        {
            valor += (c.getInteres() + c.getMonto() + c.getMora());
        }
        return valor;
    }
    
    public double valorPendiente()
    {
        return this.valorDelPrestamo() - this.totalCobrado();
    }

}
